#include "mychild.h"
#include<QtWidgets>

MyChild::MyChild()
{
    //关闭窗口时销毁
    //"当用户关闭这个窗口时，直接把它扔进回收站（删除对象），别让它占着内存了。"
    setAttribute(Qt::WA_DeleteOnClose);
    isUntitled = true;
}

//新建文件
void MyChild::newFile()
{
    static int seqNum = 1;
    isUntitled = true;
    curFile = tr("Word文档=%1").arg(seqNum++);
    setWindowTitle(curFile);
}

bool MyChild::loadFile(const QString &fileName)
{
    //isEmpty()判断对象是否有实际内容
    //isNull()判断对象是否存在
    if(!fileName.isEmpty())
    {
        //判断fileName文件名对应的文件是否存在
        if(!QFile::exists(fileName))
        {
            return false;
        }
        QFile file(fileName);
        if (!file.open(QFile::ReadOnly))
            return false;
        QByteArray data = file.readAll();

        //这两行代码的作用是 将原始数据（可能包含特殊编码）转换为Qt内部使用的Unicode字符串（QString），
        //尤其适用于处理HTML文本的编码问题。
        //Qt::codecForHtml(data) 自动检测HTML文本的编码,如果检测不到，则默认使用UTF-8或其他安全编码
        QTextCodec *codec = Qt::codecForHtml(data);
        // codec->toUnicode(data) 用检测到的编码器将原始数据转换为Unicode字符串。
        QString str = codec->toUnicode(data);

        //检查文本是否是“带格式的富文本”
        if(Qt::mightBeRichText(str))
        {
            //如果检测到富文本，直接按 HTML 格式显示。
            this->setHtml(str);
        }
        else
        {
            //如果不是富文本，走纯文本处理流程
            //将原始数据（data）按“本地系统编码”转换为字符串
            str=QString::fromLocal8Bit(data);
            this->setPlainText(str);
        }


        setCurrentFile(fileName);
        //文档的内容发生改变时,发射信号，调用documentWasModified()槽函数
        connect(document(),SIGNAL(contentsChanged()),this,SLOT(documentWasModified()));
        return true;

    }
}

//保存文件
bool MyChild::save()
{
    //检查当前文件是否未命名
    if(isUntitled)
    {
        //另存为文件
        return saveAs();
    }
    else
    {
        //直接覆盖保存到当前文件
        return saveFile(curFile);
    }
}

//另存为文件
bool MyChild::saveAs()
{
    // ？？
    QString fileName =
            QFileDialog::getSaveFileName(this,tr("另存为"),curFile,tr("HTML 文档(*.html *.html);;所有文件 (*.*)"));

    if(fileName.isEmpty())
    {
        return false;
    }

    return saveFile(fileName);

}

//覆盖保存到当前文件
bool MyChild::saveFile(QString fileName)
{
    if(!(fileName.endsWith(".htm",Qt::CaseInsensitive) || fileName.endsWith(".html",Qt::CaseInsensitive)))
    {
        //默认为HTML文档
        fileName += ".html";
    }

    //创建富文本写入器，指定保存为 HTML
    QTextDocumentWriter writer(fileName);
    //写入内容，自动将富文本转换为 HTML 并保存
    //this->document() 获取当前窗口部件（如文本编辑器）中正在操作的富文本内容对象
    bool success = writer.write(this->document());

    if(success)
    {
        //更新当前文件路径
        setCurrentFile(fileName);
    }
    return success;
}



QString MyChild::userFriendlyCurrentFile()
{
    return strippedName(curFile);
}



QString MyChild::currentFile()
{
    return curFile;
}

//格式设置
void MyChild::mergeFormationOnWordOrSelection(const QTextCharFormat &format)
{
    //QTextCursor专门用来操作文本内容
    //this->textCursor(); 用来获取当前窗口中的 “文本光标状态”（包括光标的位置、是否选中了文字、选中的是哪些文字等）
    QTextCursor cursor = this->textCursor();
    if(!cursor.hasSelection())
    {
        cursor.select(QTextCursor::WordUnderCursor);
    }
    cursor.mergeCharFormat(format);
    this->mergeCurrentCharFormat(format);
}

//设置段落对齐
void MyChild::setAligin(int align)
{
    if(align == 1)
    {
        //水平方向靠左对齐
        this->setAlignment(Qt::AlignLeft | Qt::AlignAbsolute);
    }
    else if(align == 2)
    {
        //水平方向居中
        this->setAlignment(Qt::AlignCenter);
    }
    else if(align == 3)
    {
        //水平方向靠右对齐
        this->setAlignment(Qt::AlignRight | Qt::AlignAbsolute);
    }
    else if(align == 4)
    {
        //水平方向两端对齐
        this->setAlignment(Qt::AlignJustify);
    }
}

//段落编号
void MyChild::setStyle(int style)
{
    //多行文本框文本光标插入文本
    QTextCursor cursor = this->textCursor();
    if(style != 0)
    {
        //样式为圆圈
        QTextListFormat::Style styleName = QTextListFormat::ListDisc;

        switch (style) {

        case 1:
            //样式为圆圈
            styleName = QTextListFormat::ListDisc;
            break;
        case 2:
            //样式为空心圆圈
            styleName = QTextListFormat::ListCircle;
            break;
        case 3:
            //样式为方块
            styleName = QTextListFormat::ListSquare;
            break;
        case 4:
            //样式为阿拉伯数字
            styleName = QTextListFormat::ListDecimal;
            break;
        case 5:
            //样式为小写拉丁字符 按字母顺序排序
            styleName = QTextListFormat::ListLowerAlpha;
            break;
        case 6:
            //样式为大写拉丁字符 按字母顺序排序
            styleName = QTextListFormat::ListUpperAlpha;
            break;
        case 7:
            //样式为小写拉丁字符 按字母顺序排序
            styleName = QTextListFormat::ListLowerRoman;
            break;
        case 8:
            //样式为大写拉丁字符 按字母顺序排序
            styleName = QTextListFormat::ListUpperRoman;
            break;
        default:
            break;
        }

        //1.告诉编辑器 ，要开始批量修改文本
        cursor.beginEditBlock();
        //2.看看当前段落原本的缩进是多少
        QTextBlockFormat blockFmt = cursor.blockFormat();
        //3.创建一个 “列表格式” 对象，用来设置列表的样式（如项目符号类型、缩进层级）
        QTextListFormat listFmt;
        //4.如果当前段落已经是列表（比如已经有圆圈项目符号）
        if(cursor.currentList())
        {
            //就直接在这个列表的基础上修改样式（比如换成方块），而不是重新建一个列表
            listFmt=cursor.currentList()->format();
        }
        else
        {
            //如果光标不在列表里（是普通段落），就新建列表格式
            //设置列表的缩进为 “原段落缩进 + 1
            listFmt.setIndent(blockFmt.indent() + 1);
            blockFmt.setIndent(0);
            cursor.setBlockFormat(blockFmt);
        }
        listFmt.setStyle(styleName);
        cursor.createList(listFmt);
        cursor.endEditBlock();
    }
    else
    {
        QTextBlockFormat bfmt;
        bfmt.setObjectIndex(-1);
        cursor.mergeBlockFormat(bfmt);
    }
}



void MyChild::closeEvent(QCloseEvent *event)
{
    if(maybeSave())
    {
        event->accept();
    }
    else
    {
        event->ignore();
    }
}

//设置窗口的修改状态
void MyChild::documentWasModified()
{
    //当用户没有保存文档，document()->isModified() 会为 true ,  设置窗口的修改状态
    //当用户保存文档后，document()->isModified() 会变为 false，窗口标题又会恢复成原来的样子
    setWindowModified(document()->isModified());
}


//判断是否修改并且保存文档
bool MyChild::maybeSave()
{
    //检查文本内容是否被修改过
    if(!document()->isModified())
    {
        return true;
    }
    QMessageBox::StandardButton ret;
    ret = QMessageBox::warning(this,tr("Qt Word"),
                               tr("文件'%1'已经被修改，是否保存吗？").arg(userFriendlyCurrentFile()),
                               QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);

    if(ret == QMessageBox::Save)
    {
        return save();
    }
    else if(ret == QMessageBox::Cancel)
    {
        return false;
    }

    return true;
}

//更新当前文件的状态信息，并通过界面（如窗口标题）向用户反馈文件的最新状态
void MyChild::setCurrentFile(const QString &fileName)
{
    //获取文件的标准绝对路径
    curFile = QFileInfo(fileName).canonicalFilePath();
    //标记文件已命名（不再是“未命名”状态）
    isUntitled=false;
    //重置文档的修改状态，表示内容已保存，无未保存的修改。
    document()->setModified(false);
    //清除窗口标题中的修改标记（通常是标题后的 * 号）
    setWindowModified(false);
    //更新窗口标题
    setWindowTitle(userFriendlyCurrentFile()+"[*]");
}

QString MyChild::strippedName(const QString &fullFileName)
{
    //返回文件名
    return QFileInfo(fullFileName).fileName();
}

